package com.biz.primus.ms.oms.service.collection;

import com.biz.primus.common.utils.JsonUtils;
import com.biz.primus.model.oms.enums.OrderState;
import com.biz.primus.model.oms.enums.returns.AuditState;
import com.biz.primus.model.oms.enums.returns.ReturnState;
import com.biz.primus.model.oms.stream.OrderStateChannel.OrderStreamData;
import com.biz.primus.model.oms.stream.ReturnStateChannel.ReturnStateStreamData;
import com.biz.primus.model.oms.vo.OmsChannelVo;
import com.biz.primus.model.oms.vo.OmsOrderReturnVo;
import com.biz.primus.model.oms.vo.OmsOrderVo;
import com.biz.primus.model.oms.vo.returns.RefundRequestVo;
import com.biz.primus.ms.base.service.AbstractBaseService;
import com.biz.primus.ms.oms.dao.po.OmsOrder;
import com.biz.primus.ms.oms.dao.po.OrderPaymentInfo;
import com.biz.primus.ms.oms.dao.po.returns.OmsRefund;
import com.biz.primus.ms.oms.dao.po.returns.OmsReturn;
import com.biz.primus.ms.oms.dao.repository.*;
import com.biz.primus.ms.oms.service.channel.ChannelService;
import com.biz.primus.ms.oms.service.logs.OrderLogsService;
import com.biz.primus.ms.oms.stream.OrderStateSource;
import com.biz.primus.ms.oms.stream.ReturnStateSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author yanweijin
 * @date 2017/10/31
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class OmsCollectionServiceImpl extends AbstractBaseService implements OmsCollectionService{


	@Autowired
	private OmsOrderRepository omsOrderRepository;

	@Autowired
	private OmsPaymentRepository omsPaymentRepository;

	@Autowired
	private OrderDataConverter dataConverter;

	@Autowired
	private OmsConsigneeRepository omsConsigneeRepository;

	@Autowired
	private OrderStateSource orderStateSource;
	@Autowired
	private ReturnStateSource returnStateSource;

	@Autowired
	private OrderLogsService orderLogsService;

	@Autowired
	private OmsOrderReturnRepository omsOrderReturnRepository;

	@Autowired
	private OmsRefundRepository omsRefundRepository;

	@Autowired
	private ChannelService channelService;




	@Override
	public void collectionOrder(OmsOrderVo vo) {

		log.info("oms-collector: 收到订单:{}", JsonUtils.obj2Json(vo));

		//检查订单号
		if(isNotEffectiveOrderCode(vo.getCode())){
			//记录收单日志
			orderLogsService.logOrderCollection(vo,"订单编号不合法,未记录");
			//记录系统日志
			log.error("oms-collector: 订单编号不合法, orderCode={}",vo.getCode());
			return;
		}else{
			orderLogsService.logOrderCollection(vo,"收到订单:"+vo.getCode());
			log.info("oms-collector: 订单号[{}]验证成功",vo.getCode());
		}

		//查询并验证渠道 todo
		OmsChannelVo channel = channelService.findChannelByCode(vo.getChannel());


		//转换订单/支付单/收货人 vo 2 po
		OmsOrder order = dataConverter.orderVo2Po(vo);
		List<OrderPaymentInfo> payments = dataConverter.paymentVo2Po(vo.getPayments(), order.getId());
		omsConsigneeRepository.save(order.getConsignee());
		omsOrderRepository.save(order);
		omsPaymentRepository.save(payments);

		delayer.executeAfterTransactionCommit(()->{
			//事务成功提交后发送消息流
			OrderStreamData streamData = new OrderStreamData(order.getOrderCode(), vo.getExpectDepot());
			Message<OrderStreamData> msg = MessageBuilder.withPayload(streamData).build();
			OrderState state = order.getState();
			if(state == OrderState.begin){
				orderStateSource.orderBeginOutput().send(msg);
			}else if(state ==OrderState.outbound){
				orderStateSource.orderOutboundOutput().send(msg);
			}else{
				orderStateSource.orderFinishedOutput().send(msg);
			}
		});
	}

	@Override
	public void collectionReturn(OmsOrderReturnVo vo) {

		//检查订单号
		if (isNotEffectiveReturnCode(vo.getCode())) {
			//记录收单日志
			orderLogsService.logOrderReturnCollection(vo, "退单编号不合法,未记录");
			//记录系统日志
			log.error("oms-collector: 订单编号不合法, returnCode={}", vo.getCode());
			return;
		} else {
			orderLogsService.logOrderReturnCollection(vo, "收到退单:"+vo.getCode());
			if (log.isDebugEnabled()) {
				log.debug("oms-collector: 收到订单:{}", JsonUtils.obj2Json(vo));
			}
		}

		//查询并验证渠道
		OmsChannelVo channel = channelService.findChannelByCode(vo.getChannel());


		//查出原订单
		OmsOrder omsOrder = omsOrderRepository.findByOrderCode(vo.getOriginOrderCode());

		OmsReturn omsReturn = dataConverter.returnVo2Po(vo,omsOrder);
		ReturnState rState = vo.getReturnState();

		//如果是已完成的退货单,需要填写签收人信息
		if(rState==ReturnState.finished){
			omsReturn.setReturnState(rState);
			omsReturn.setAuditState(AuditState.pass);
			omsReturn.setReceiver(vo.getReceiver());
			omsReturn.setReceiveTime(vo.getReceiveTime());
		}

		omsOrderReturnRepository.save(omsReturn);

		delayer.executeAfterTransactionCommit(()->{
			ReturnStateStreamData payload = ReturnStateStreamData.builder().returnId(omsReturn.getId()).returnCode(omsReturn.getReturnCode())
					.needInbound(channel.isOnlineChannel()).needRefund(vo.isNeedRefund() || channel.isOnlineChannel())
					.build();
			Message<ReturnStateStreamData> msg = MessageBuilder.withPayload(payload).build();
			returnStateSource.getChannelByReturnState(omsReturn.getReturnState()).send(msg);
		});
	}

	@Override
	public void collectionRefund(RefundRequestVo vo) {
		//检查订单号
		if (isNotEffectiveRefundCode(vo.getRefundCode())) {
			//记录收单日志
			orderLogsService.logOrderRefundCollection(vo, "退款单编号不合法,未记录");
			//记录系统日志
			log.error("oms-collector: 订单编号不合法, returnCode={}", vo.getRefundCode());
			return;
		} else {
			orderLogsService.logOrderRefundCollection(vo, "收到退款单:"+vo.getRefundCode());
			if (log.isDebugEnabled()) {
				log.debug("oms-collector: 收到订单:{}", JsonUtils.obj2Json(vo));
			}
		}

		OmsRefund omsRefund = dataConverter.refundVo2Po(vo);
		omsRefundRepository.save(omsRefund);
	}


	private boolean isNotEffectiveOrderCode(String code){
		return StringUtils.isBlank(code) || omsOrderRepository.isExistOrder(code)>0;
	}

	private boolean isNotEffectiveReturnCode(String code){
		return StringUtils.isBlank(code) || omsOrderReturnRepository.isExistOrder(code) > 0;
	}

	private boolean isNotEffectiveRefundCode(String code){
		return StringUtils.isBlank(code) || omsRefundRepository.isExistOrder(code) > 0;
	}

}
